package com.gitee.fantaros.engine;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.*;
import java.util.logging.LogManager;
import java.util.logging.Logger;

public class FanJsEngine {

    private static final FanJsEngine instance = new FanJsEngine();

    public static FanJsEngine getInstance() {
        return instance;
    }

    private static final Logger log = Logger.getLogger("FanJsEngine");

    public static Logger getLog() {
        return log;
    }

    private final ScriptEngine scriptEngine;

    private FanJsEngine() {
        this.scriptEngine = new ScriptEngineManager().getEngineByName("nashorn");
        this.scriptEngine.put("engine", this);
        this.scriptEngine.put("js", this.scriptEngine);
        this.scriptEngine.put("jout", System.out);
        this.scriptEngine.put("jin", System.in);
        this.scriptEngine.put("jerr", System.err);
    }

    public void loadJsFromRes(String resourceName) throws Exception {
        try (InputStream inputStream = FanJsEngine.class.getModule().getResourceAsStream(resourceName)) {
            try (InputStreamReader inputStreamReader = new InputStreamReader(inputStream)) {
                evalJs(resourceName, inputStreamReader);
            }
        }
    }

    public void loadJs(String path) throws Exception {
        try (Reader reader = new FileReader(path)) {
            evalJs(path, reader);
        }
    }

    public String getThrowableInfo(Throwable throwable) {
        try (StringWriter stringWriter = new StringWriter();
             PrintWriter printWriter = new PrintWriter(stringWriter, true)) {
            throwable.printStackTrace(printWriter);
            return String.join(": \r\n", throwable.getMessage(), stringWriter.getBuffer().toString());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void evalJs(String srcName, Reader reader) {
        log.info(String.format("load js lib: %1$s start", srcName));
        try {
            this.scriptEngine.eval(reader);
            log.info(String.format("load js lib: %1$s finished", srcName));
        } catch (Exception e) {
            log.warning(String.format("load js lib: %1$s failed", srcName));
            log.warning(getThrowableInfo(e));
        }
    }

    public void info(String msg) {
        log.info(msg);
    }
}
